package com.carbohydrate42.kotlin_compose_demo.compose

import android.annotation.SuppressLint
import android.content.Context
import android.net.Uri
import android.os.Environment
import android.util.Log
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.core.content.FileProvider
import com.carbohydrate42.kotlin_compose_demo.BuildConfig
import com.carbohydrate42.kotlin_compose_demo.api.FileApi
import com.carbohydrate42.kotlin_compose_demo.util.UriUtil
import kotlinx.coroutines.launch
import okhttp3.MultipartBody
import okhttp3.RequestBody.Companion.asRequestBody
import java.io.File
import java.util.Date

private fun getStorageFileUri(
    filePrefix: String,
    fileSuffix: String,
    context: Context
): Uri {
    val storageFile: File? =
        if (Environment.MEDIA_MOUNTED == Environment.getExternalStorageState()) {
            context.externalCacheDir
        } else {
            context.cacheDir
        }


    // 暂时只是存在 app 自身的缓存下目录下的
    // 参考 android 应用文件目录
    // https://developer.android.com/training/data-storage/app-specific?hl=zh-cn
    val photoFile = File.createTempFile(
        filePrefix,
        fileSuffix,
        storageFile
    ).apply {
        createNewFile()
        deleteOnExit()
    }

    return FileProvider.getUriForFile(context, "${BuildConfig.APPLICATION_ID}.provider", photoFile)
}

private fun getExternalCacheFileName(path: String?): String? {

    if (path == null) {
        return null
    }
    return path
        .split("/")
        .dropLastWhile { it.isEmpty() }
        .toTypedArray()
        .last()
}



@SuppressLint("Range")
@Preview(showBackground = true, showSystemUi = true)
@Composable
fun FileUploader() {

    val context = LocalContext.current

    val coroutineScope = rememberCoroutineScope()

    var storageImageFileUri by remember {
        mutableStateOf<Uri?>(null)
    }

    var storageVideoFileUri by remember {
        mutableStateOf<Uri?>(null)
    }

    val requestPermission =
        rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
            if (isGranted) {
                Log.i("Permission: ", "Granted")
            } else {
                Log.i("Permission: ", "Denied")
            }
        }


    LaunchedEffect(Unit) {
        requestPermission.launch(android.Manifest.permission.READ_EXTERNAL_STORAGE)
    }


    val pickMediaAndUpload =
        rememberLauncherForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri ->
            Log.d("FileUploader", "uri: ${uri?.path}")

            UriUtil.getPath(context, uri)?.let { realFilePath ->
                File(realFilePath).let { file ->
                    MultipartBody
                        .Builder()
                        .setType(MultipartBody.FORM)
                        .addFormDataPart("file", file.name, file.asRequestBody())
                        .build()
                        .let { requestBody ->
                            coroutineScope.launch {
                                FileApi.instance.upload(requestBody)
                            }
                        }
                }

            }
        }

    // 拍的照片存储在应用的外部 cache 专属目录下
    val takePictureAndUpload =
        rememberLauncherForActivityResult(ActivityResultContracts.TakePicture()) { takePictureSuccess ->
            if (takePictureSuccess) {

                getExternalCacheFileName(storageImageFileUri?.path)?.let { fileName ->
                    File(context.externalCacheDir?.path, fileName).let { file ->
                        MultipartBody
                            .Builder()
                            .setType(MultipartBody.FORM)
                            .addFormDataPart("file", file.name, file.asRequestBody())
                            .build()
                            .let { requestBody ->
                                coroutineScope.launch {
                                    FileApi.instance.upload(requestBody)
                                }
                            }
                    }
                }

            }
        }

    val captureVideoAndUpload =
        rememberLauncherForActivityResult(ActivityResultContracts.CaptureVideo()) { captureVideoSuccess ->
            if (captureVideoSuccess) {
                getExternalCacheFileName(storageVideoFileUri?.path)?.let { fileName ->
                    File(context.externalCacheDir?.path, fileName).let { file ->
                        MultipartBody
                            .Builder()
                            .setType(MultipartBody.FORM)
                            .addFormDataPart("file", file.name, file.asRequestBody())
                            .build()
                            .let { requestBody ->
                                coroutineScope.launch {
                                    FileApi.instance.upload(requestBody)
                                }
                            }
                    }
                }

            }
        }



    Column {
        Button(onClick = {
            pickMediaAndUpload.launch(
                PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageAndVideo)
            )
        }) {
            Text(text = "选择系统相册的视频或图片, 并上传")
        }

        Button(onClick = {
            storageImageFileUri = getStorageFileUri(
                "capture_picture_${Date().time}",
                ".png",
                context
            )

            takePictureAndUpload.launch(storageImageFileUri)
        }) {
            Text(text = "调用系统拍照片, 并直接上传")
        }

        Button(onClick = {
            storageVideoFileUri = getStorageFileUri(
                "capture_video_${Date().time}",
                ".mp4",
                context
            )

            captureVideoAndUpload.launch(storageVideoFileUri)
        }) {
            Text(text = "调用系统录像, 并直接上传")
        }
    }
}